import { ipairs, pairs } from "@/utils/lua"
import { Buff, BuffData, BuffDataSet } from "./Buff"
import { customAlphabet } from "nanoid"
import Basic from "@/global"
import { cloneDeep, isNil } from "lodash-es"
import { FightPlayer } from "./Fightplayer"
import { Aura, AuraData } from "./Aura"
import { Battle } from "./Battle"
import { table } from "@/utils/lua/table"
import { effectTable } from "@/data/EffectTable"
import { Skill, SkillData, SkillDataSet } from "./Skill"
import { skillTable } from "@/data/SkillTable"
const nanoid = customAlphabet("1234567890abcdef", 8)
export interface CharacterDataSet {
  speed: number
  name: string,
  atk: [number, number],
  maxHP: number,
  maxMP: number,
  auras: number[]
  skills?:number[]
}
/**
 * @description 用于数据传输
 */
export class CharacterData {
  id: string
  character_id: number
  player!: string
  maxHP: number
  maxMP: number
  atk: [number, number]
  name: string
  auras: AuraData[]
  buffs: BuffData[] = []
  skills:SkillData[] = []
  creator?: string
  templet: {

  }

  constructor(charactor_id: number) {
    this.character_id = charactor_id
    this.id = nanoid()
    const data = Basic.character[charactor_id]
    this.maxHP = data.maxHP
    this.maxMP = data.maxMP
    this.atk = data.atk
    this.name = data.name
    this.templet = {
      maxHP: data.maxHP,
      maxMP: data.maxMP,
      atk: data.atk
    }
    this.auras = data.auras.map(aura_id => {
      const aura: AuraData = {
        id: nanoid(),
        aura_id: aura_id,
        character_id: this.id,
        caster_id: '1',
        host_id: this.id,
      }
      return aura
    })
    this.skills = data.skills?.map(item=>{
      return {
        id: nanoid(),
        skillId: item,
        cd: -1
      }
    }) || []
  }
}


export class Character {
  id: string
  name!: string

  maxHP!: number;
  currentHP!: number;
  maxMP!: number;
  currentMP!: number;
  atk!: [number, number];
  dead: boolean = false
  player!: FightPlayer
  auras: Aura[] = []
  buffs: Buff[] = []
  skills: Skill[] = []
  battle: Battle
  character_id!: number
  templet!: Record<string, any>
  dirty: boolean = false
  private _temppro = {}
  get temppro() {
    const pro = {
      maxHP: this.maxHP,
      currentHP: this.currentHP,
      maxMP: this.maxMP,
      currentMP: this.currentMP,
      atk: this.atk,
      doomed: false,
      deathrattle: []
    }
    for (let buff of this.buffs) {
      buff.pro?.(pro)
    }
    return pro
  }
  creator?: Character
  oriData!: CharacterData
  constructor(id: string, data: CharacterData, battle: Battle) {
    this.id = id
    this.battle = battle
    this.init(data)
  }

  init(data: CharacterData) {
    this.oriData = data
    this.character_id = data.character_id
    this.templet = cloneDeep(Basic.character[this.character_id]) || {}
    this.templet.maxHP = data.templet.maxHP || this.templet.maxHP
    this.templet.maxMP = data.templet.maxMP || this.templet.maxMP
    //  局外属性
    this.name = this.templet.name
    this.maxHP = data.maxHP
    this.currentHP = this.maxHP
    this.maxMP = data.maxMP
    this.currentMP = this.maxMP
    this.atk = data.atk
    this.name = data.name
    this.skills = data.skills
    // 重置局内属性
    this.reset(data)

    // 生成buff和aura
    this.initBuff()
  }

  reset(character: CharacterData) {
    character = character || {}
    // 局内属性
    this.maxHP = character.maxHP
    this.maxMP = character.maxMP
    this.atk = character.atk
    this.dead = false
    // 重置buff，保留永久buff
    const oldbuffs = this.buffs
    this.buffs = []
    oldbuffs.forEach((buff) => {
      if (buff.permanent) {
        this.buffs.push(buff)
      }
    })
  }

  initBuff() {
    // 必须先统一初始化一次
    this.buffs = []
    // 设置创建者
    if (this.oriData.creator) {
      this.creator = this.battle.getDerivative(this.oriData.creator)
    }
    // 初始化buff和effect
    this.buffs = []
    this.auras = this.auras || []
    this.oriData.buffs?.forEach((buff, i) => {
      let caster = this.battle.getDerivative(buff.caster_id)
      let host = this.battle.getDerivative(buff.host_id)
      let newBuff = this.addBuff(
        buff.id,
        buff.buff_id,
        caster,
        host || this,
        buff.custom_num
      )
      if (newBuff && this.battle.derivatives[newBuff.id]) {
        newBuff.aura = this.battle.derivatives[newBuff.id]
      }
    })
    // 删除旧的光环和buff
    this.auras.map((aura) => {
      // 判断旧光环是否还存在
      let isori = (this.oriData.auras || []).some((oriaura) => {
        if (oriaura.id == aura.id) {
          return true
        }
      })
      if (!isori) {
        this.removeAura(aura.id)
      }
    })

      ; (this.oriData.auras || []).forEach((aura) => {
        let caster = this.battle.getDerivative(aura.caster_id)
        let host = this.battle.getDerivative(aura.host_id)
        this.addAura(
          aura.id,
          aura.aura_id,
          caster,
          host || this,
          aura.custom_num,
          aura.card_id
        )
      })
  }

  refreshAuras() {
    const [pos, field] = this.getfield()
    this.auras.forEach((aura, i) => {
      let oldtars: Record<string, Character | null> = aura.tars || {}
      let newtars: Record<string, Character> = {}
      if (aura.condition && (aura.condition(this, pos, field, this.battle))) {
        aura.range.pos.forEach((range: string) => {
          if (!this.player) return
          let rangetars: Record<string, Fightcard> = {}
          if (range === "self") {
            rangetars[this.id] = this
          } else if (range === "global") {
            if (!this.player.global) return
            rangetars[this.player.global.id] = this.player.global
          } else if (range === 'enemy') {
            this.player.opponent.fields.forEach(item => {
              if (!item) return
              rangetars[item.id] = item
            })
          }

          for (let i in rangetars) {
            let tar = rangetars[i]
            if (aura.range.condition(this, tar, { aura }, this.battle)) {
              newtars[tar.id] = tar
            }
          }
        })
      }
      // if(Object.keys(newtars).length === 3){
      //     debugger
      // }
      // 添加新buff
      for (let i in newtars) {
        let fightcard = newtars[i]
        for (let buff_id of aura.buffs) {
          let buff = fightcard.addBuff(aura.id, buff_id, this, fightcard)
          if (buff) {
            buff.aura = aura
          }
        }
        oldtars[fightcard.id] = null
      }
      // 删除光环失效的buff
      for (let i in oldtars) {
        let fightcard = oldtars[i]
        fightcard?.removeBuff(aura.id)
      }
      aura.tars = newtars

    })
  }

  removeAura(id: string) {
    this.auras.forEach((aura, i) => {
      if (aura.id === id) {
        this.auras.splice(i, 1)
        this.battle.derivatives[id] = null
      }
      // 删除光环失效的buff
      let oldtars = aura.tars || {}
      for (let i in oldtars) {
        oldtars[i].removeBuff(id)
      }
    })
  }
  addAura(id: string, aura_id: number, caster: Character | undefined, host: Character, custom_num: number | undefined, card_id: string) {
    for (let aura of this.auras) {
      if (aura.id === id) {
        if (custom_num) {
          aura.custom_num = custom_num
        }
        aura.card_id = card_id
        return aura
      }
    }
    let aura = cloneDeep(Basic.aura[aura_id])
    aura.id = id
    aura.aura_id = aura_id
    aura.caster = caster
    aura.host = host
    aura.custom_num = custom_num || 0
    aura.card_id = card_id || 0
    this.auras.push(aura)
    this.battle.derivatives[id] = aura
  }

  addBuff(id: string, buff_id: number, caster: Character | undefined, host: Character, custom_num?: number) {
    for (let buff of this.buffs) {
      if (buff.id == id) {
        if (!isNil(custom_num)) {
          buff.custom_num = custom_num
        }
        buff.caster = caster
        return buff
      }
    }

    let buff = new Buff(id, buff_id, caster, host, custom_num, this.battle)
    this.buffs.push(buff)
    return buff
  }
  findBuff(id: number) {
    return this.buffs.find(item => item.buff_id === id)
  }

  removeBuff(id: string) {
    for (const [i, buff] of ipairs(this.buffs)) {
      if (buff.id === id) {
        this.buffs.splice(i, 1)
        return
      }
    }
  }

  async activateEffects(timing, para) {
    let buffs = table.copy(this.buffs);
    for (let [_, _buff] of ipairs(buffs)) {
      for (let [_, eff] of pairs(_buff.effects)) {
        // 在eff执行过程中 buff可能存在被改变的情况 所以要重新定位
        let buff = this.buffs.find(item => item.id === _buff.id)!
        if (eff.timing === timing) {
          await effectTable[eff.id].func?.call({ character: this, buff, effect: eff, battle: this.battle }, timing, para)
        }
      }
    }
  }
  activateCounter(timing, para) {

  }
  getfield() {
    return []
  }
}